package com.easy.project.service.system.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.easy.project.base.exception.ServiceException;
import com.easy.project.constant.MenuTypeEnum;
import com.easy.project.constant.StatusEnum;
import com.easy.project.convert.MenuDomainConvert;
import com.easy.project.domain.dto.auth.LoginDTO;
import com.easy.project.domain.po.system.SysRolePO;
import com.easy.project.domain.po.system.SysUserPO;
import com.easy.project.domain.vo.system.SysAuthVO;
import com.easy.project.domain.vo.system.SysMenuVO;
import com.easy.project.domain.vo.system.SysUserInfoVO;
import com.easy.project.service.system.*;
import com.easy.project.util.SaTokenUtils;
import org.springframework.stereotype.Service;
import cn.dev33.satoken.stp.SaLoginConfig;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.easy.project.base.result.SystemErrorCodeEnum.LOGIN_ERROR;

/**
 * <p>
 * 鉴权 服务实现类
 * </p>
 *
 * @author wxz
 * @since 2024-01-10
 */
@Service
public class SysAuthServiceImpl extends BaseAuthServiceImpl implements ISysAuthService {

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ISysRoleService sysRoleService;

    @Resource
    private ISysMenuService sysMenuService;

    @Resource
    private MenuDomainConvert menuDomainConvert;

    @Override
    public String generateRsaPublicKey() {
        SaTokenUtils.RsaKey rsaKey = SaTokenUtils.generateRsaKey();
        // 缓存rsa key
        super.cacheRsk(rsaKey);
        return rsaKey.getPublicKey();
    }

    @Override
    public SysAuthVO login(LoginDTO loginDTO) {
        // String cachePrivateKey = super.getCachePrivateKey(loginDTO.getPublicKey());
        // 解密password
        // String password = SaTokenUtils.decryptRsaPassword(loginDTO.getPassword(), cachePrivateKey);
        // String encryptPassword = SaTokenUtils.generatePassword(password);

        SysUserPO sysUserPO = sysUserService.getOne(new LambdaQueryWrapper<SysUserPO>()
                .eq(SysUserPO::getUserName, loginDTO.getUserName())
                .eq(SysUserPO::getPassword, loginDTO.getPassword())
                .eq(SysUserPO::getStatus, StatusEnum.USABLE.getCode()));
        if (Objects.isNull(sysUserPO)) {
            throw new ServiceException(LOGIN_ERROR);
        }
        // 登录成功后封装用户的信息
        StpUtil.login(sysUserPO.getId(),SaLoginConfig
                .setExtra(SaTokenUtils.IS_ADMIN,sysUserPO.getAdmin()));
        return buildAuthInfo(sysUserPO.getId());
    }

    /**
     * 根据用户id获取用户的权限信息
     * @param userId
     * @return
     */
    private SysAuthVO buildAuthInfo(Long userId){
        // 获取用户基本信息
        SysUserInfoVO sysUserInfoVO = sysUserService.userInfo(userId);
        // 获取用户所有的角色id
        List<Long> roleIdList = sysRoleService.getRoleByUserId(userId).stream().map(SysRolePO::getId).collect(Collectors.toList());
        // 根据角色id获取所有菜单
        List<SysMenuVO> sysMenuVOList;
        if (SaTokenUtils.isAdmin()){
            sysMenuVOList = sysMenuService.allMenu();
        }else {
            sysMenuVOList = sysMenuService.getMenuByRoleId(roleIdList);
        }

        SysAuthVO res = new SysAuthVO();
        res.setToken(StpUtil.getTokenValue());
        res.setSysUserInfoVO(sysUserInfoVO);
        res.setMenuList(sysMenuVOList);
        return res;
    }

    @Override
    public List<String> getPermissionListByUserId(Long userId) {
        // 管理员拿到所有权限
        if (SaTokenUtils.isAdmin()){
            return sysMenuService.allPath();
        }
        List<SysRolePO> sysRolePOList = sysRoleService.getRoleByUserId(userId);
        // 根据角色id获取菜单权限
        List<SysMenuVO> sysMenuVOList = sysMenuService.getMenuByRoleId(sysRolePOList.stream().map(SysRolePO::getId).collect(Collectors.toList()));
        // 根据菜单id获取接口权限
        return sysMenuVOList.stream().filter(e -> Objects.equals(e.getMenuType(), MenuTypeEnum.INTERFACE.getCode())).map(SysMenuVO::getMenuRouter).collect(Collectors.toList());
    }

    @Override
    public List<String> getRoleCodeListByUserId(Long userId) {
        return sysRoleService.getRoleByUserId(userId).stream().map(SysRolePO::getRoleCode).collect(Collectors.toList());
    }

    @Override
    public List<String> getAllPermissionList() {
        return sysMenuService.allMenu().stream().map(SysMenuVO::getMenuRouter).collect(Collectors.toList());
    }

    @Override
    public List<String> getAllRoleCode() {
        return sysRoleService.list().stream().map(SysRolePO::getRoleCode).collect(Collectors.toList());
    }

    @Override
    public void loginOut() {
        StpUtil.logout();
    }

}
